package com.whfc.wxmp.api.sys.service.impl;

import com.whfc.base.service.SmsService;
import com.whfc.common.enums.SysRulePlatform;
import com.whfc.common.exception.BizException;
import com.whfc.common.result.ResultEnum;
import com.whfc.common.util.AssertUtil;
import com.whfc.common.util.DateV2Util;
import com.whfc.entity.dto.statistics.StatisticsProgressDTO;
import com.whfc.entity.dto.statistics.StatisticsProgressUnitDTO;
import com.whfc.fuum.dto.SysRuleDTO;
import com.whfc.fuum.dto.WxRuleDTO;
import com.whfc.fuum.dto.WxUserDTO;
import com.whfc.fuum.entity.SysUser;
import com.whfc.fuum.entity.UserBaseDTO;
import com.whfc.fuum.entity.WxUser;
import com.whfc.fuum.param.WxUserParam;
import com.whfc.fuum.service.SysUserService;
import com.whfc.fuum.service.WxUserService;
import com.whfc.quality.enums.QualityCheckUserType;
import com.whfc.quality.service.QualityCheckService;
import com.whfc.safety.service.SafetyCheckService;
import com.whfc.wxmp.api.sys.service.WxUsersService;
import com.whfc.wxmp.dto.UserDetailDTO;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author qzexing
 * @version 1.0
 * @date 2020-12-12 17:24
 */
@Service
public class WxUsersServiceImpl implements WxUsersService {

    @DubboReference(interfaceClass = WxUserService.class, version = "1.0.0")
    private WxUserService wxUserService;

    @DubboReference(interfaceClass = SysUserService.class, version = "1.0.0")
    private SysUserService sysUserService;

    @DubboReference(interfaceClass = SmsService.class, version = "1.0.0")
    private SmsService smsService;

    @DubboReference(interfaceClass = QualityCheckService.class, version = "1.0.0")
    private QualityCheckService qualityCheckService;

    @DubboReference(interfaceClass = SafetyCheckService.class, version = "1.0.0")
    private SafetyCheckService safetyCheckService;

    @Override
    public WxUserDTO getUserById(Integer wxUserId) {
        WxUser wxUser = wxUserService.getUserById(wxUserId);
        WxUserDTO userDTO = new WxUserDTO();
        BeanUtils.copyProperties(wxUser, userDTO);
        return userDTO;
    }

    @Override
    public void updateUserName(WxUser loginUser, String name) {
        wxUserService.updateUserName(loginUser, name);
    }

    @Override
    public void updateUserPhone(WxUser loginUser, String phone, String code) {
        //验证手机验证码
        smsService.checkSmsCode(phone, code);
        //修改手机号
        wxUserService.updateUserPhone(loginUser, phone);
    }

    @Override
    public List<WxRuleDTO> getUserRuleList(WxUser loginUser) {
        List<SysRuleDTO> ruleList = sysUserService.getMpUserRuleList(loginUser, SysRulePlatform.MP.getValue());
        //将rule 处理成树形嵌套
        List<WxRuleDTO> wxRuleTree = getWxRuleTree(ruleList);
        wxRuleTree.sort(Comparator.comparingInt(WxRuleDTO::getIndex));
        return wxRuleTree;
    }

    @Override
    public List<WxRuleDTO> getUserRuleList(WxUser loginUser, Integer deptId) {
        String phone = loginUser.getPhone();
        SysUser sysUser = sysUserService.getUserByPhone(phone);
        List<SysRuleDTO> ruleList = sysUserService.getUserRuleListByDeptId(sysUser, SysRulePlatform.MP.getValue(), deptId);
        //将rule 处理成树形嵌套
        List<WxRuleDTO> wxRuleTree = getWxRuleTree(ruleList);
        wxRuleTree.sort(Comparator.comparingInt(WxRuleDTO::getIndex));
        return wxRuleTree;
    }

    @Override
    public void editUserInfo(WxUserParam param) {
        wxUserService.editUserInfo(param);
    }

    @Override
    public UserDetailDTO getPrjDetail(Integer deptId, Integer wxUserId, String phone) {

        UserBaseDTO userInfo = sysUserService.getUserBase(deptId, wxUserId, phone);
        Integer userId = userInfo.getUserId();

        if (userId == null) {
            UserDetailDTO res = new UserDetailDTO();
            userInfo.setWxUserId(wxUserId);
            res.setUserInfo(userInfo);
            return res;
        }
        String startTime = DateV2Util.startTime();
        String endTime = DateV2Util.endTime();
        StatisticsProgressDTO quality = qualityCheckService.getStatisticsProgressDTO(deptId, userId, startTime, endTime);
        StatisticsProgressDTO safety = safetyCheckService.getStatisticsProgressDTO(deptId, userId, startTime, endTime);


        //将安全和质量的统计数据组合再统计
        Map<Integer, List<StatisticsProgressUnitDTO>> map = new HashMap<>();
        quality.getTaskProgressList().forEach(m -> {
            List<StatisticsProgressUnitDTO> qualityList = map.get(m.getScene());
            if (qualityList == null) {
                qualityList = new ArrayList<>();
                map.put(m.getScene(), qualityList);
            }
            qualityList.add(m);
        });

        safety.getTaskProgressList().forEach(n -> {
            List<StatisticsProgressUnitDTO> safetyList = map.get(n.getScene());
            if (safetyList == null) {
                safetyList = new ArrayList<>();
                map.put(n.getScene(), safetyList);
            }
            safetyList.add(n);
        });

        //QualityCheckUserType/SafetyCheckUserType
        List<Integer> sceneList = Stream.of(QualityCheckUserType.RECTIFIER.getValue(), QualityCheckUserType.REVIEWER.getValue(), QualityCheckUserType.VERIFIER.getValue()).collect(Collectors.toList());
        List<StatisticsProgressUnitDTO> taskProgressList = new ArrayList();

        for (Integer scene : sceneList) {

            StatisticsProgressUnitDTO data = new StatisticsProgressUnitDTO();
            data.setScene(scene);

            List<StatisticsProgressUnitDTO> list = map.get(scene);
            if (CollectionUtils.isEmpty(list)) {
                data.setCompleteCount(0);
                data.setTotal(0);
                data.setRate("100%");
                taskProgressList.add(data);
                continue;
            }

            int completeCount = list.stream().mapToInt(StatisticsProgressUnitDTO::getCompleteCount).sum();
            int total = list.stream().mapToInt(StatisticsProgressUnitDTO::getTotal).sum();
            data.setCompleteCount(completeCount);
            data.setTotal(total);
            if (total == 0) {
                data.setRate("100%");
                taskProgressList.add(data);
                continue;
            }

            String rate = new BigDecimal(completeCount * 100).divide(new BigDecimal(total), 0, RoundingMode.HALF_UP).toString();
            data.setRate(rate);
            taskProgressList.add(data);
        }

        StatisticsProgressDTO progress = new StatisticsProgressDTO();
        progress.setReportCount(quality.getReportCount() + safety.getReportCount());
        progress.setCheckCount(quality.getCheckCount() + safety.getCheckCount());
        progress.setTaskProgressList(taskProgressList);

        UserDetailDTO res = new UserDetailDTO();
        userInfo.setWxUserId(wxUserId);
        res.setUserInfo(userInfo);
        res.setProgressInfo(progress);
        return res;
    }

    /**
     * 微信权限树结构处理
     *
     * @param ruleList 权限列表
     * @return 权限树结构
     */
    private List<WxRuleDTO> getWxRuleTree(List<SysRuleDTO> ruleList) {
        List<WxRuleDTO> list = new ArrayList<>();
        for (SysRuleDTO sysRuleDTO : ruleList) {
            WxRuleDTO wxRuleDTO = new WxRuleDTO();
            BeanUtils.copyProperties(sysRuleDTO, wxRuleDTO);
            list.add(wxRuleDTO);
        }
        return parseTree(list);
    }

    /**
     * 格式成树结构
     *
     * @param list 权限集合
     * @return
     */
    private List<WxRuleDTO> parseTree(List<WxRuleDTO> list) {
        List<WxRuleDTO> result = new ArrayList<>();
        // 1、获取第一级节点
        for (WxRuleDTO wxRuleDTO : list) {
            if (0 == wxRuleDTO.getPid()) {
                result.add(wxRuleDTO);
            }
        }
        // 2、递归获取子节点
        for (WxRuleDTO wxRuleDTO : result) {
            recursiveTree(wxRuleDTO, list);
        }
        return result;
    }

    /**
     * 递归处理
     *
     * @param parent 权限
     * @param list   权限集合
     */
    private void recursiveTree(WxRuleDTO parent, List<WxRuleDTO> list) {
        for (WxRuleDTO wxRuleDTO : list) {
            if (parent.getRuleId().equals(wxRuleDTO.getPid())) {
                recursiveTree(wxRuleDTO, list);
                List<WxRuleDTO> children = parent.getChildren();
                if (children == null) {
                    children = new ArrayList<>();
                    parent.setChildren(children);
                }
                children.add(wxRuleDTO);
            }
        }
    }


    private SysUser get(String phone) {
        AssertUtil.isTrue(StringUtils.isBlank(phone), "手机号信息缺失");
        SysUser user = sysUserService.getUserByPhone(phone);
        if (user == null) {
            throw new BizException(ResultEnum.NOT_FOUND.getCode(), "请联系管理员添加账号");
        }
        return user;
    }
}
